package com.le.medium.class7;

import org.junit.Test;

/**
 * 完全二叉树节点数量
 * 思路：
 *  1. 遍历依次获取所有节点数量 时间复杂度O（n）
 *  2. 通过判断左右子树深度是否与最大深度一致，得到左、右是满二叉树，在遍历求解一边 时间复杂度O(log n)
 */
public class Problem05_CompleteTreeNodeNumber {
    public static class Node {
        int val;
        Node left;
        Node right;

        public Node(int val) {
            this.val = val;
        }
    }

    public static int getNum(Node head) {
        if (head == null) {
            return 0;
        }
        return process(head, 1, MostLeftLevel(head, 1));
    }

    private static int process(Node head, int level, int h) {
        if (level == h) {
            return 1;
        }
        if (MostLeftLevel(head.right, level + 1) == h) {
            // 说明左子树是满二叉树
            return (1 << (h - level)) + process(head.right, level + 1, h);
        } else {
            // 右子树是满二叉树
            return (1 << (h - level - 1)) + process(head.left, level + 1, h);
        }
    }

    private static int MostLeftLevel(Node node, int level) {
        while (node != null) {
            level++;
            node = node.left;
        }
        return level - 1;
    }

    @Test
    public void test(){
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        System.out.println(getNum(head));
    }
}
